﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model.Instance;
using l1cs.server.serverpackets;
using l1cs.server.model.skill;
using System.Threading;

namespace l1cs.server.model
{
    public class L1Chaser
    {
        private static Logger _log = Logger.getLogger( typeof( L1Chaser ).FullName );

        private static Random _random = new Random();

        private Timer _future = null;

        private int _timeCounter = 0;

        private L1PcInstance _pc;

        private L1Character _cha;

        public L1Chaser( L1PcInstance pc, L1Character cha )
        {
            _cha = cha;
            _pc = pc;
        }

        public void L1ChaserTimerSub(object state)
        {
            if ( _cha == null || _cha.isDead() )
            {
                stop();
                return;
            }
            attack();
            _timeCounter++;
            if ( _timeCounter >= 3 )
            {
                stop();
                return;
            }
        }

        public void begin()
        {
            // 効果時間が8秒のため、4秒毎のスキルの場合処理時間を考慮すると実際には1回しか効果が現れない
            // よって開始時間を0.9秒後に設定しておく
            // TODO 優先度9 タイマースレッド
            //_future = GeneralThreadPool.getInstance().scheduleAtFixedRate( this, 0, 1000 );
            _future = new Timer( new TimerCallback( L1ChaserTimerSub ), null, 0, 1000 );
        }

        public void stop()
        {
            if ( _future != null )
            {
                _future.Dispose();
            }
        }

        public void attack()
        {
            double damage = getDamage( _pc, _cha );
            if ( _cha.getCurrentHp() - (int)damage <= 0
                    && _cha.getCurrentHp() != 1 )
            {
                damage = _cha.getCurrentHp() - 1;
            }
            else if ( _cha.getCurrentHp() == 1 )
            {
                damage = 0;
            }
            S_EffectLocation packet = new S_EffectLocation( _cha.getX(), _cha.getY(), 7025 );
            _pc.sendPackets( packet );
            _pc.broadcastPacket( packet );
            if ( _cha is L1PcInstance )
            {
                L1PcInstance pc = (L1PcInstance)_cha;
                pc.sendPackets( new S_DoActionGFX( pc.getId(), ActionCodes.ACTION_Damage ) );
                pc.broadcastPacket( new S_DoActionGFX( pc.getId(), ActionCodes.ACTION_Damage ) );
                pc.receiveDamage( _pc, damage, false );
            }
            else if ( _cha is L1NpcInstance )
            {
                L1NpcInstance npc = (L1NpcInstance)_cha;
                npc.broadcastPacket( new S_DoActionGFX( npc.getId(), ActionCodes.ACTION_Damage ) );
                npc.receiveDamage( _pc, (int)damage );
            }
        }

        public double getDamage( L1PcInstance pc, L1Character cha )
        {
            double dmg = 0;
            int spByItem = pc.getSp() - pc.getTrueSp();
            int intel = pc.getInt();
            int charaIntelligence = pc.getInt() + spByItem - 12;
            double coefficientA = 1.0 + 3.0 / 32.0 * charaIntelligence;
            if ( coefficientA < 1 )
            {
                coefficientA = 1.0;
            }
            double coefficientB = 0;
            if ( intel > 18 )
            {
                coefficientB = ( intel + 2.0 ) / intel;
            }
            else if ( intel <= 12 )
            {
                coefficientB = 12.0 * 0.065;
            }
            else
            {
                coefficientB = intel * 0.065;
            }
            double coefficientC = 0;
            if ( intel <= 12 )
            {
                coefficientC = 12;
            }
            else
            {
                coefficientC = intel;
            }
            dmg = ( _random.Next( 6 ) + 1 + 7 ) * coefficientA * coefficientB / 10.5 * coefficientC * 2.0;

            dmg = L1WeaponSkill.calcDamageReduction( pc, cha, dmg, 0 );

            if ( cha.hasSkillEffect( L1SkillId.IMMUNE_TO_HARM ) )
            {
                dmg /= 2.0;
            }

            return dmg;
        }

    }
}
